/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012-2013 Oliver Katz */

#include "mod_argbuf.h"
#include "../../common/debug.h"

namespace sleepyface
{
    namespace arch
    {
        namespace modules
        {
        	ArgumentBuffer::ArgumentBuffer() : ArchModule()
        	{
        		setName("argument-buffer");
        	}

        	int ArgumentBuffer::add(string n, char c, string v, string d, Architecture &a)
        	{
        		if (c != 0)
        			set(n, "short", ModuleValue(ModuleValue::_int, (int)c), a);
        		else
        			set(n, "", ModuleValue(), a);

        		if (!v.empty())
        			set(n, "value", ModuleValue(ModuleValue::_string, v), a);

        		if (!d.empty())
        			set(n, "description", ModuleValue(ModuleValue::_string, d), a);

        		return 0;
        	}

			ModuleValue ArgumentBuffer::get(string k0, string k1, Architecture &a)
			{
				if (k0.compare("version") == 0 && k1.empty())
					return ModuleValue(ModuleValue::_string, version);
				else if (k0.compare("author") == 0 && k1.empty())
					return ModuleValue(ModuleValue::_string, author);
				else if (k0.compare("year") == 0 && k1.empty())
					return ModuleValue(ModuleValue::_int, year);
				else if (k1.compare("value") == 0)
					return ModuleValue(ModuleValue::_string, string(strdup(z_arg_buffer_value_get(&abuf, (char *)k0.c_str()))));
				else if (k1.compare("flag") == 0)
					return ModuleValue(ModuleValue::_bool, z_arg_buffer_flag_get(&abuf, (char *)k0.c_str()));
				else
					return ModuleValue();
			}

			ModuleValue ArgumentBuffer::set(string k0, string k1, ModuleValue v, Architecture &a)
			{
				int e = 0;

				if (k1.empty())
				{
					if ((e = z_arg_buffer_append(&abuf, (char *)k0.c_str())) != 0)
					{
						Z_WARNING("z_arg_buffer_append failed (" << e << ")");
						return ModuleValue();
					}
					Z_DEBUG(verbose, "added argument " << k0);
					return v;
				}
				else if (k1.compare("short") == 0)
				{
					if ((e = z_arg_buffer_append_with_shorthand(&abuf, (char *)k0.c_str(), (char)v.getInt())) != 0)
					{
						Z_WARNING("z_arg_buffer_append_with_shorthand failed (" << e << ")");
						return ModuleValue();
					}
					Z_DEBUG(verbose, "added argument " << k0 << " (shorthand " << (char)v.getInt() << ")");
					return v;
				}
				else if (k1.compare("description") == 0)
				{
					if ((e = z_arg_buffer_describe(&abuf, (char *)k0.c_str(), strdup(v.getString().c_str()))) != 0)
					{
						Z_WARNING("z_arg_buffer_describe failed (" << e << ")");
						return ModuleValue();
					}
					Z_DEBUG(verbose, "describing argument " << k0 << " (" << v.getString() << ")");
					return v;
				}
				else if (k1.compare("value") == 0)
				{
					if (z_arg_buffer_value_set(&abuf, (char *)k0.c_str(), strdup(v.getString().c_str())) == NULL)
					{
						Z_WARNING("z_arg_buffer_value_set failed (NULL)");
						return ModuleValue();
					}
					Z_DEBUG(verbose, "setting argument " << k0 << " (" << v.getString() << ")");
					return v;
				}
				else
				{
					Z_WARNING("unknown set format");
					Z_NOTE("k0", k0);
					Z_NOTE("k1", k1);
					return ModuleValue();
				}
			}

			int ArgumentBuffer::signal(ModuleSignal s, Architecture &a)
			{
				if (s.getCode() == signalInitialize)
				{
					abuf = z_arg_buffer_init(1024, strdup((a.getName()+" [OPTIONS]").c_str()));
					version = "0.01";
					author = "";
					year = __YEAR__; // NOTE: not predefined G++ macro, but defined within makefile
					return 0;
				}
				else if (s.getCode() == signalUninitialize)
				{
					z_arg_buffer_release(abuf);
					return 0;
				}
				else if (s.getCode() == signalCommandLineArguments)
				{
					if ((!version.empty() && !author.empty()) && year > 0)
						z_arg_buffer_sign(&abuf, strdup(a.getName().c_str()), strdup(version.c_str()), strdup(author.c_str()), year);
					return z_init_args(&abuf, a.getArgc(), a.getArgv());
				}
				else
				{
					return 0;
				}
			}
		}
	}
}